package SnmpClients;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */


import java.io.IOException;
import org.snmp4j.PDU;
import org.snmp4j.ScopedPDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.UserTarget;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.AuthMD5;
import org.snmp4j.security.PrivDES;
import org.snmp4j.security.SecurityLevel;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.security.UsmUser;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;


/**
 * Classe responsável por fazer a ligação ao agente e fazer query's de forma segura e confidêncial.
 * Mais especificamente, utiliza SNMP v3, tendo portanto autênticação e encriptação.
 */
public class SnmpClienteV3 
{
    private Snmp snmp;
    private UserTarget servidor_snmp;
    
    /**
     * Construtor
     * 
     * @param servidor_ip_porta IP do servidor e da respectiva porta, em que o agente está a ouvir
     * @param utilizador Nome do utilizador
     * @param MD5Pass Palavra-chave MD5
     * @param DESPass Palavra-chave DES
     * @throws IOException
     */
    public SnmpClienteV3(String servidor_ip_porta, String utilizador, String MD5Pass, String DESPass) throws IOException
    {
        setTarget(servidor_ip_porta);
        
        TransportMapping transport = new DefaultUdpTransportMapping();
        snmp = new Snmp(transport);
        
        USM usm = new USM(SecurityProtocols.getInstance(),
                     new OctetString(MPv3.createLocalEngineID()), 0);
        SecurityModels.getInstance().addSecurityModel(usm);
        
        snmp.getUSM().addUser(new OctetString(utilizador), 
                new UsmUser(new OctetString(utilizador), 
                        AuthMD5.ID, 
                        new OctetString(MD5Pass), 
                        PrivDES.ID, 
                        new OctetString(DESPass)));
        
        snmp.listen();
    }
    
    /**
     * Vai buscar o valor de um objecto
     * 
     * @param oid OID do objecto do qual se pretende capturar o valor
     * @return Valor do objecto correspondente ao OID indicado
     * @throws IOException
     */
    public String getAsString(OID oid) throws IOException 
    {
        PDU pdu = new ScopedPDU();
        pdu.add(new VariableBinding(oid));
        pdu.setType(PDU.GET);
        ResponseEvent event = snmp.send(pdu, servidor_snmp);
        if(event != null) 
        {
             return event.getResponse().get(0).getVariable().toString();
        }
        throw new RuntimeException("GET timed out");
    }
    
    /**
     * Vai buscar o valor de varios objectos
     * 
     * @param oid OID's dos objectos do qual se pretende capturar o valor
     * @return PDU com os valores dos objectos
     * @throws IOException
     */
    public ResponseEvent getListAsString(OID[] oid) throws IOException{
        PDU pdu = new ScopedPDU();
        //pdu.add(new VariableBinding(oid));
        for(OID o : oid)
            pdu.add(new VariableBinding(o));
        //pdu.addAll(vbs);
        pdu.setType(PDU.GET);
        ResponseEvent event = snmp.send(pdu, servidor_snmp);
        if(event != null) 
        {
             return event;//.get(0).getVariable().toString();
        }
        throw new RuntimeException("GET timed out");
    }
    
    
    /**
     * Define o agente ao qual o cliente snmpv3 se vai ligar
     * 
     * @param address Endereço IP e porta do agente
     */
    public void setTarget(String address) 
    {
        Address targetAddress = GenericAddress.parse(address);
        
        servidor_snmp = new UserTarget();
        servidor_snmp.setAddress(targetAddress);
        servidor_snmp.setRetries(2);
        servidor_snmp.setTimeout(1500);
        servidor_snmp.setVersion(SnmpConstants.version3);
        servidor_snmp.setSecurityLevel(SecurityLevel.AUTH_NOPRIV);
        servidor_snmp.setSecurityName(new OctetString("gk"));
    }
}
